package ferus.tigris.lines;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;

import android.graphics.Point;
import ferus.tigris.lines.levels.LevelManager;
import ferus.tigris.lines.personages.AbstractBehavior;
import ferus.tigris.lines.data.DB;
import ferus.tigris.lines.data.PersonageInfo;


public class GameManager extends Thread {
	private GameView view;
	private boolean running = false;
	
	private Matrix marks = new Matrix();
	private LevelManager levels = new LevelManager(this);
	
	Deque<AbstractBehavior> queue = new ArrayDeque<AbstractBehavior>();
	private List<PersonageInfo> personages = new ArrayList<PersonageInfo>();
	
	public void setRunning(boolean run) {
		running = run;
	}

	public GameManager(GameView gameView) {
		view = gameView;
	}
	
	public void setPersonages(Matrix marks, Deque<AbstractBehavior> queue) {
		synchronized (view.getHolder()) {
			this.marks = marks;
			view.setSprites(marks, queue);
		}
	}
	
	private void trySleep(long l) {
		try {
			sleep(l);
		} catch (InterruptedException e) {

		}		
	}
	
	public void run() {
		long ticksPS = 100;

		levels.start();
		
		while (running) {
	
			long startTime = System.currentTimeMillis();
			synchronized (view.getHolder()) {
				if(!personages.isEmpty()) {
					levels.fill(personages);
					personages.clear();
					levels.check();
				}
				update();
			}
			long sleepTime = ticksPS-(System.currentTimeMillis() - startTime);
			trySleep(sleepTime < 20 ? 20 : sleepTime);
		}
	}

	private void update() {
		for(AbstractBehavior mark: marks.getMarks()) {
			mark.update();
		}
		removeDiedPersonages();	
	}

	private void removeDiedPersonages() {
		for(AbstractBehavior mark: marks.getMarks()) {
			if(mark.isDied()) {
				levels.died(mark);
			}
		}
	}

	public GameView view() {
		return view;
	}

	public void onTouch(float x, float y) {
		Point p = new Point((int)x - view().gameField().left, (int)y - view().gameField().top);
		synchronized (view.getHolder()) {
			levels.onTouch(p);
		}
		
		checkLevel();
	}

	protected void checkLevel() {
		levels.check();
	}

	public double levelScopeScale() {
		return levels.scopeScale();
	}

	public void load(DB db) {
		if(db.isSave()) {
			long level_id = db.loadLastLevelId();
			levels.load(db.loadLevel(level_id), db.loadLevelScope(level_id), db.loadLevelComplexity(level_id));
			personages = db.loadPersonages(level_id);
		}
	}

	public void save(DB db) {
		long level_id = db.saveLevel(levels.levelType(), levels.scope(), levels.complexity());
		db.savePersonages(level_id, levels.personages());
	}

	public void playLevelCompliteSound() {
		view.sounds().playLevelComplite();
	}

	public void playLevelFailSound() {
		view.sounds().playLevelFail();
	}

	public int scope() {
		return levels.scope();
	}

	public void onLevelFail() {
		view.saveResult();
	}

	public void saveResult(DB db) {
		db.addResult(levels.scope());
	}

}
